/*
 * Copyright 2012-2014 the original author or authors.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except
 * in compliance with the License. You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package com.jqd.framework.core.hessian.biz.action.support;

import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import com.jqd.framework.core.hessian.biz.action.ActionHandlerInterceptor;
import com.jqd.framework.core.hessian.biz.action.ActionHandlerMapping;
import com.jqd.framework.core.hessian.model.ServiceRequest;
import com.jqd.framework.core.hessian.model.ServiceResponse;
import com.jqd.framework.util.Assert;

/**
 * 
 * TODO
 * 
 * @author liaozhicheng.cn@gmail.com
 * @date 2012-6-11
 * @since 1.0
 */
public abstract class AbstractActionHandlerMapping implements ActionHandlerMapping,
		ApplicationContextAware, Order {
	
	protected static final Log log = LogFactory.getLog(AbstractActionHandlerMapping.class);
	
	private ActionHandlerInterceptor[] interceptors;
	
	// key : ServiceRequest中设置的actionId
	// value : MultiMethodAction对象，即应用系统中的具体的Action实例
	private final Map<String, Object> handlerCacheMappings = new HashMap<String, Object>();
	
	
	protected void registerHandler(String actionId, Object handler) {
		this.handlerCacheMappings.put(actionId, handler);
	}
	
	
	protected void registerHandler(Map<String, Object> handleMap) {
		this.handlerCacheMappings.putAll(handleMap);
	}
	
	
	protected Object getHandlerCache(String actionId) {
		return this.handlerCacheMappings.get(actionId);
	}
	
	
	/**
	 * @return the interceptors
	 */
	public ActionHandlerInterceptor[] getInterceptors() {
		return interceptors;
	}
	
	
	/**
	 * @param interceptors
	 *            the interceptors to set
	 */
	public final void setInterceptors(ActionHandlerInterceptor[] interceptors) {
		if (interceptors != null && interceptors.length > 0) {
			OrderComparator.sort(interceptors);
		}
		
		this.interceptors = interceptors;
	}
	
	
	@Override
	public ActionHandlerExecution getHandler(ServiceRequest serviceRequest) {
		
		String actionId = serviceRequest.getRequestedActionID();
		Assert.hasText(actionId, "Property 'REQUESTED_ACTION_ID' can not be null or empty");
		
		Object handler = getHandlerCache(actionId);
		if (handler == null) {
			handler = getHandlerInternal(serviceRequest);
		}
		
		return handler != null ? new ActionHandlerExecution(handler, getInterceptors()) : null;
	}
	
	
	protected abstract Object getHandlerInternal(ServiceRequest serviceRequest);
	
	
	/**
	 * 判断某个方法是否是一个能够处理controller请求的方法 标准的action中的方法判断标准：1）传入参数只有一个，2）入参类型为 {@link ServiceRequest}；
	 * 3）返回参数类型为 {@link ServiceResponse}；满足上面3个条件返回true，否则返回false
	 * 
	 * @param method
	 * @return
	 */
	protected boolean isHandlerMethod(Method method) {
		Class<?> returnType = method.getReturnType();
		boolean effectReturnType = returnType == ServiceResponse.class;
		
		Class<?>[] parameterTypes = method.getParameterTypes();
		boolean effectParameterType = parameterTypes.length == 1;
		if (effectParameterType) {
			effectParameterType &= (parameterTypes[0] == ServiceRequest.class);
		}
		
		return effectReturnType && effectParameterType;
	}
	
	
	protected void logInfo(String actionId, Object handler) {
		if (log.isInfoEnabled()) {
			log.info(new StringBuilder().append(" ==== ").append(this.getClass().getSimpleName())
					.append(" find action handler mapping : [").append(actionId).append("] --> ")
					.append(" '").append(handler.getClass().getName()).append("' ====").toString());
		}
	}
	
	
	// ---------------------------------------------------
	// implements ApplicationContextAware
	//
	// 1.在容器启动的时候，由子类初始化所有的映射，并缓存
	// 2.#initAllHandleMapping方法提供默认的实现，子类通过覆盖它实现一些初始化逻辑，
	// 如果初始化之后不需要一些额外的逻辑，则无需覆盖
	// 3.这里只是处理好每个actionId到具体Action对象的映射，并没有处理actionId到具体Action中某个方法的映射
	// ---------------------------------------------------
	
	@Override
	public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
		initAllHandleMapping(applicationContext);
	}
	
	
	protected void initAllHandleMapping(ApplicationContext applicationContext) {
		// 子类覆盖该方法实现一些初始化逻辑
		// 提供默认实现，因为某些子类可能不需要初始化逻辑，则无需提供额外覆盖
	}
	
	// ----------------------------------------------------
	// implements Order
	//
	// 用于排序，在配置了多个ActionHandlerMapping实现时
	// 如果没有明确配置优先级，则具有最高优先级
	// ----------------------------------------------------
	
	// 用于排序的参数，如果用户配置了多个ActionHandlerMapping实现
	// 可以通过设置该参数来设定作用顺序
	private int order = Order.HIGHEST_PRECEDENCE;
	
	
	public final int getOrder() {
		return order;
	}
	
	
	public final void setOrder(int order) {
		this.order = order;
	}
	
}
